/* $Id: MainActivity.java 5022 2015-03-25 03:41:21Z nanang $ */
/*
 * Copyright (C) 2013 Teluu Inc. (http://www.teluu.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package com.hollycrm.sipdemo;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.design.widget.TextInputEditText;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;


import org.pjsip.pjsua2.AccountConfig;
import org.pjsip.pjsua2.AuthCredInfo;
import org.pjsip.pjsua2.AuthCredInfoVector;
import org.pjsip.pjsua2.BuddyConfig;
import org.pjsip.pjsua2.CallInfo;
import org.pjsip.pjsua2.CallOpParam;
import org.pjsip.pjsua2.OnRegStateParam;
import org.pjsip.pjsua2.StringVector;
import org.pjsip.pjsua2.pjsip_inv_state;
import org.pjsip.pjsua2.pjsip_status_code;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import hollycrm.com.libuip.http.ConfigAPI;
import hollycrm.com.libuip.http.UIPConfig;
import hollycrm.com.libuip.http.UIPRequest;
import hollycrm.com.libuip.internal.SocketIOClient;
import hollycrm.com.libuip.sip.SipApp;
import hollycrm.com.libuip.sip.UIPAccount;
import hollycrm.com.libuip.sip.UIPBuddy;
import hollycrm.com.libuip.sip.UIPCall;
import hollycrm.com.libuip.socket.SocketClient;
import hollycrm.com.libuip.socket.UIPMessage;
import hollycrm.com.libuip.utils.UIPMessageAdapter;
import okhttp3.HttpUrl;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;


public class MainActivity extends AppCompatActivity
        implements Handler.Callback, SipApp.SipObserver {
    public static SipApp app = null;
    public static UIPCall currentCall = null;
    public static UIPAccount account = null;
    public static AccountConfig accCfg = null;

    private ListView buddyListView;
    private SimpleAdapter buddyListAdapter;
    private int buddyListSelectedIdx = -1;
    ArrayList<Map<String, String>> buddyList;
    private String lastRegStatus = "";

    private TextView socketStatus;

    private final Handler handler = new Handler(this);
    public class MSG_TYPE {
        public final static int INCOMING_CALL = 1;
        public final static int CALL_STATE = 2;
        public final static int REG_STATE = 3;
        public final static int BUDDY_STATE = 4;
        public final static int CALL_MEDIA_STATE = 5;
    }

    private HashMap<String, String> putData(String uri, String status) {
        HashMap<String, String> item = new HashMap<>();
        item.put("uri", uri);
        item.put("status", status);
        return item;
    }

    private void showCallActivity() {
        Intent intent = new Intent(this, CallActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        socketStatus = (TextView) findViewById(R.id.socket_status);

        if (app == null) {
            app = new SipApp();
            // Wait for GDB to init, for native debugging only
            //noinspection PointlessBooleanExpression
            if (false && (getApplicationInfo().flags &
                    ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {}
            }

            app.init(this, getFilesDir().getAbsolutePath());
        }

        if (app.accList.size() == 0) {
            accCfg = new AccountConfig();
            accCfg.setIdUri("sip:31031");
            accCfg.getNatConfig().setIceEnabled(true);
            accCfg.getNatConfig().setIceAlwaysUpdate(true);
            //accCfg.getNatConfig().setIceNoRtcp(true);
            //accCfg.getNatConfig().setTurnEnabled(false);
            accCfg.getVideoConfig().setAutoTransmitOutgoing(true);
            accCfg.getVideoConfig().setAutoShowIncoming(true);
            account = app.addAcc(accCfg);
        } else {
            account = app.accList.get(0);
            accCfg = account.cfg;
        }

//        buddyList = new ArrayList<>();
//        for (int i = 0; i < account.buddyList.size(); i++) {
//            buddyList.add(
//                    putData(account.buddyList.get(i).cfg.getUri(),
//                    account.buddyList.get(i).getStatusText())
//            );
//        }
//        String[] from = { "uri", "status" };
//        int[] to = { android.R.id.text1, android.R.id.text2 };
//        buddyListAdapter = new SimpleAdapter(
//                this, buddyList,
//                android.R.layout.simple_list_item_2,
//                from, to);
//
//        buddyListView = (ListView) findViewById(R.id.listViewBuddy);
//        buddyListView.setAdapter(buddyListAdapter);
//        buddyListView.setOnItemClickListener(
//                new AdapterView.OnItemClickListener() {
//                    @Override
//                    public void onItemClick(AdapterView<?> parent,
//                                            final View view, int position, long id) {
//                        view.setSelected(true);
//                        buddyListSelectedIdx = position;
//                    }
//                }
//        );

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar
        // if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.action_acc_config:
                dlgAccountSetting();
                break;
            case R.id.action_quit:
                Message m = Message.obtain(handler, 0);
                m.sendToTarget();
                break;
            case R.id.action_http_config:
                editUipconfig();
            default:
                break;
        }
        return true;
    }

    @Override
    public boolean handleMessage(Message m) {
        if (m.what == 0) {
            app.deinit();
            finish();
            Runtime.getRuntime().gc();
            android.os.Process.killProcess(android.os.Process.myPid());

        } else if (m.what == MSG_TYPE.CALL_STATE) {
            CallInfo ci = (CallInfo) m.obj;
            /* Forward the message to CallActivity */
            if (CallActivity.handler_ != null) {
                Message m2 = Message.obtain(CallActivity.handler_,
                        MSG_TYPE.CALL_STATE, ci);
                m2.sendToTarget();
            }
        } else if (m.what == MSG_TYPE.CALL_MEDIA_STATE) {
            /* Forward the message to CallActivity */
            if (CallActivity.handler_ != null) {
                Message m2 = Message.obtain(CallActivity.handler_,
                        MSG_TYPE.CALL_MEDIA_STATE, null);
                m2.sendToTarget();
            }
        } else if (m.what == MSG_TYPE.BUDDY_STATE) {
//            UIPBuddy buddy = (UIPBuddy) m.obj;
//            int idx = account.buddyList.indexOf(buddy);
//            /* Update buddy status text, if buddy is valid and
//            * the buddy lists in account and UI are sync-ed.*/
//            if (idx >= 0 && account.buddyList.size() == buddyList.size()) {
//                buddyList.get(idx).put("status", buddy.getStatusText());
//                buddyListAdapter.notifyDataSetChanged();
//                // TODO: selection color/mark is gone after this,
//                //       dont know how to return it back.
//                //buddyListView.setSelection(buddyListSelectedIdx);
//                //buddyListView.performItemClick(buddyListView,
//                //				     buddyListSelectedIdx,
//                //				     buddyListView.
//                //		    getItemIdAtPosition(buddyListSelectedIdx));
//
//                /* Return back Call activity */
//                notifyCallState(currentCall);
//            }
        } else if (m.what == MSG_TYPE.REG_STATE) {
            String msg_str = (String) m.obj;
            lastRegStatus = msg_str;
        } else if (m.what == MSG_TYPE.INCOMING_CALL) {
            /* Incoming call */
            final UIPCall call = (UIPCall) m.obj;
            CallOpParam prm = new CallOpParam();
            /* Only one call at anytime */
            if (currentCall != null) {
                /*
                prm.setStatusCode(pjsip_status_code.PJSIP_SC_BUSY_HERE);
                try {
                    call.hangup(prm);
                } catch (Exception e) {}
                */
                // TODO: set status code
                call.delete();
                return true;
            }
            /* Answer with ringing */
            prm.setStatusCode(pjsip_status_code.PJSIP_SC_RINGING);
            try {
                call.answer(prm);
            } catch (Exception e) {}
            currentCall = call;
            showCallActivity();
        } else {
            /* Message not handled */
            return false;
        }
        return true;
    }


    private void dlgAccountSetting() {
        LayoutInflater li = LayoutInflater.from(this);
        View view = li.inflate(R.layout.dlg_account_config, null);
        if (lastRegStatus.length()!=0) {
            TextView tvInfo = (TextView)view.findViewById(R.id.textViewInfo);
            tvInfo.setText("Last status: " + lastRegStatus);
        }

        AlertDialog.Builder adb = new AlertDialog.Builder(this);
        adb.setView(view);
        adb.setTitle("Account Settings");

        final EditText etId    = (EditText)view.findViewById(R.id.editTextId);
        final EditText etReg   = (EditText)view.findViewById(R.id.editTextRegistrar);
        final EditText etProxy = (EditText)view.findViewById(R.id.editTextProxy);
        final EditText etUser  = (EditText)view.findViewById(R.id.editTextUsername);
        final EditText etPass  = (EditText)view.findViewById(R.id.editTextPassword);

        etId.setText(accCfg.getIdUri());
        etReg.setText(accCfg.getRegConfig().getRegistrarUri());
        StringVector proxies = accCfg.getSipConfig().getProxies();
        if (proxies.size() > 0)
            etProxy.setText(proxies.get(0));
        else
            etProxy.setText("");
        AuthCredInfoVector creds = accCfg.getSipConfig().getAuthCreds();
        if (creds.size() > 0) {
            etUser. setText(creds.get(0).getUsername());
            etPass. setText(creds.get(0).getData());
        } else {
            etUser. setText("");
            etPass. setText("");
        }
        adb.setCancelable(false);
        adb.setPositiveButton(android.R.string.ok,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,int id) {
                        String acc_id    = etId.getText().toString();
                        String registrar = etReg.getText().toString();
                        String proxy     = etProxy.getText().toString();
                        String username  = etUser.getText().toString();
                        String password  = etPass.getText().toString();
                        accCfg.setIdUri(acc_id);
                        accCfg.getRegConfig().setRegistrarUri(registrar);
                        AuthCredInfoVector creds = accCfg.getSipConfig().getAuthCreds();
                        creds.clear();
                        if (username.length() != 0) {
                            creds.add(
                                    new AuthCredInfo("Digest", "*", username, 0, password)
                            );
                        }
                        StringVector proxies = accCfg.getSipConfig().getProxies();
                        proxies.clear();
                        if (proxy.length() != 0) {
                            proxies.add(proxy);
                        }
                        /* Enable ICE */
                        accCfg.getNatConfig().setIceEnabled(true);
                        /* Finally */
                        lastRegStatus = "";
                        try {
                            account.modify(accCfg);
                        } catch (Exception e) {}
                    }
                }
        );
        adb.setNegativeButton(
                android.R.string.cancel,
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,int id) {
                        dialog.cancel();
                    }
                }
        );

        AlertDialog ad = adb.create();
        ad.show();
    }

    @SuppressWarnings("unchecked")
    public void makeCall(View view) {
        if (buddyListSelectedIdx == -1)
            return;

        /* Only one call at anytime */
        if (currentCall != null) {
            return;
        }

        HashMap<String, String> item = (HashMap<String,String>) buddyListView.
				       getItemAtPosition(buddyListSelectedIdx);
        String buddy_uri = item.get("uri");

        UIPCall call = new UIPCall(account, -1);
        CallOpParam prm = new CallOpParam(true);
        try {
            call.makeCall(buddy_uri, prm);
        } catch (Exception e) {
            call.delete();
            return;
        }

        currentCall = call;
        showCallActivity();
    }

//    private void dlgAddEditBuddy(BuddyConfig initial) {
//        final BuddyConfig cfg = new BuddyConfig();
//        final BuddyConfig old_cfg = initial;
//        final boolean is_add = initial == null;
//
//        LayoutInflater li = LayoutInflater.from(this);
//        View view = li.inflate(R.layout.dlg_add_buddy, null);
//
//        AlertDialog.Builder adb = new AlertDialog.Builder(this);
//        adb.setView(view);
//
//        final EditText etUri  = (EditText)view.findViewById(R.id.editTextUri);
//        final CheckBox cbSubs = (CheckBox)view.findViewById(R.id.checkBoxSubscribe);
//
//        if (is_add) {
//            adb.setTitle("Add Buddy");
//        } else {
//            adb.setTitle("Edit Buddy");
//            etUri. setText(initial.getUri());
//            cbSubs.setChecked(initial.getSubscribe());
//        }
//
//        adb.setCancelable(false);
//        adb.setPositiveButton("OK",
//            new DialogInterface.OnClickListener()
//            {
//            public void onClick(DialogInterface dialog,int id)
//            {
//                cfg.setUri(etUri.getText().toString());
//                cfg.setSubscribe(cbSubs.isChecked());
//
//                if (is_add) {
//                account.addBuddy(cfg);
//                buddyList.add(putData(cfg.getUri(), ""));
//                buddyListAdapter.notifyDataSetChanged();
//                buddyListSelectedIdx = -1;
//                } else {
//                if (!old_cfg.getUri().equals(cfg.getUri())) {
//                    account.delBuddy(buddyListSelectedIdx);
//                    account.addBuddy(cfg);
//                    buddyList.remove(buddyListSelectedIdx);
//                    buddyList.add(putData(cfg.getUri(), ""));
//                    buddyListAdapter.notifyDataSetChanged();
//                    buddyListSelectedIdx = -1;
//                } else if (old_cfg.getSubscribe() !=
//                       cfg.getSubscribe())
//                {
//                    UIPBuddy bud = account.buddyList.get(
//                                buddyListSelectedIdx);
//                    try {
//                    bud.subscribePresence(cfg.getSubscribe());
//                    } catch (Exception e) {}
//                }
//                }
//            }
//            }
//        );
//        adb.setNegativeButton("Cancel",
//            new DialogInterface.OnClickListener()
//            {
//            public void onClick(DialogInterface dialog,int id) {
//                dialog.cancel();
//            }
//            }
//        );
//
//        AlertDialog ad = adb.create();
//        ad.show();
//    }
//
//    public void addBuddy(View view) {
//        dlgAddEditBuddy(null);
//    }

//    public void editBuddy(View view) {
//        if (buddyListSelectedIdx == -1)
//            return;
//        BuddyConfig old_cfg = account.buddyList.get(buddyListSelectedIdx).cfg;
//        dlgAddEditBuddy(old_cfg);
//    }

//    @SuppressWarnings("unchecked")
//    public void delBuddy(View view) {
//        if (buddyListSelectedIdx == -1)
//            return;
//        final HashMap<String, String> item = (HashMap<String, String>)
//			buddyListView.getItemAtPosition(buddyListSelectedIdx);
//        String buddy_uri = item.get("uri");
//
//        DialogInterface.OnClickListener ocl =
//                        new DialogInterface.OnClickListener()
//        {
//            @Override
//            public void onClick(DialogInterface dialog, int which)
//            {
//            switch (which) {
//                case DialogInterface.BUTTON_POSITIVE:
//                account.delBuddy(buddyListSelectedIdx);
//                buddyList.remove(item);
//                buddyListAdapter.notifyDataSetChanged();
//                buddyListSelectedIdx = -1;
//                break;
//                case DialogInterface.BUTTON_NEGATIVE:
//                break;
//            }
//            }
//        };
//
//        AlertDialog.Builder adb = new AlertDialog.Builder(this);
//        adb.setTitle(buddy_uri);
//        adb.setMessage("\nDelete this buddy?\n");
//        adb.setPositiveButton("Yes", ocl);
//        adb.setNegativeButton("No", ocl);
//        adb.show();
//    }


    /*
    * === UIPObserver ===
    * 
    * As we cannot do UI from worker thread, the callbacks mostly just send
    * a message to UI/main thread.
    */


    @Override
    public void notifyIncomingCall(UIPCall call) {
        Message m = Message.obtain(handler, MSG_TYPE.INCOMING_CALL, call);
        m.sendToTarget();
    }

    @Override
    public void notifyRegState(pjsip_status_code code, String reason, int expiration) {
        String msg_str = "";
        if (expiration == 0)
            msg_str += "Unregistration";
        else
            msg_str += "Registration";

        if (code.swigValue()/100 == 2)
            msg_str += " successful";
        else
            msg_str += " failed: " + reason;

        Message m = Message.obtain(handler, MSG_TYPE.REG_STATE, msg_str);
        m.sendToTarget();
    }

    @Override
    public void notifyCallState(UIPCall call) {
        if (currentCall == null || call.getId() != currentCall.getId())
            return;
        CallInfo ci;
        try {
            ci = call.getInfo();
        } catch (Exception e) {
            ci = null;
        }
        Message m = Message.obtain(handler, MSG_TYPE.CALL_STATE, ci);
        m.sendToTarget();

        if (ci != null &&
            ci.getState() == pjsip_inv_state.PJSIP_INV_STATE_DISCONNECTED) {
            currentCall = null;
        }
    }

    @Override
    public void notifyCallMediaState(UIPCall call) {
        Message m = Message.obtain(handler, MSG_TYPE.CALL_MEDIA_STATE, null);
        m.sendToTarget();
    }

    @Override
    public void notifyBuddyState(UIPBuddy buddy) {
        Message m = Message.obtain(handler, MSG_TYPE.BUDDY_STATE, buddy);
        m.sendToTarget();
    }

    /* === end of UIPObserver ==== */

    private void modifyAccount(String acc_id,String registrar,String proxy,String username,String password ) {
        accCfg.setIdUri(acc_id);
        accCfg.getRegConfig().setRegistrarUri(registrar);
        AuthCredInfoVector creds = accCfg.getSipConfig().getAuthCreds();
        creds.clear();
        if (username.length() != 0) {
            creds.add(
                    new AuthCredInfo("Digest", "*", username, 0, password)
            );
        }
        StringVector proxies = accCfg.getSipConfig().getProxies();
        proxies.clear();
        if (proxy.length() != 0) {
            proxies.add(proxy);
        }
                        /* Enable ICE */
        accCfg.getNatConfig().setIceEnabled(true);
                        /* Finally */
        lastRegStatus = "";
        try {
            account.modify(accCfg);
        } catch (Exception e) {}
    }


    public void login(View view ) {
        socketClient.send(gson.toJson(UIPMessage.getSignIn(
                workno,deviceno,config.phoneconfig.SkillDesc
        )));
    }

    public void logout(View view) {
        socketClient.send(gson.toJson(UIPMessage.getSignOut(
                workno
        )));
    }

    public void notReady(View view) {
        socketClient.send(gson.toJson(UIPMessage.getAgentNotReady(
                workno
        )));
    }

    public void ready(View view) {
        socketClient.send(gson.toJson(UIPMessage.getAgentReady(
                workno
        )));
    }

    public void reset(View view ){
        socketClient.send(gson.toJson(UIPMessage.getReset(
                workno
        )));
    }

    public void sipCall(View view){
        socketClient.send(gson.toJson(UIPMessage.getMakeCall(
                workno,
                deviceno,
                1,
                outcallNum,
                deviceno
        )));
    }


    private static SocketClient socketClient;

    private ConfigAPI configAPI;

    private UIPConfig config;

    private Gson gson;

    private static String ip = "47.93.80.230";
    private static int port = 18081;
    private static String workno = "1040";
    private static String deviceno = "31030";
    private static String outcallNum = "31033";

    public void editUipconfig() {
        View view = getLayoutInflater().inflate(R.layout.dig_uip_config,null);
        final TextInputEditText ipEt = (TextInputEditText) view.findViewById(R.id.server_ip);
        final TextInputEditText portEt = (TextInputEditText) view.findViewById(R.id.server_port);
        final TextInputEditText deviceNo = (TextInputEditText) view.findViewById(R.id.device_no);
        final TextInputEditText workNo = (TextInputEditText) view.findViewById(R.id.work_no);
        final TextInputEditText outCallTx = (TextInputEditText) view.findViewById(R.id.out_call_no);
        ipEt.setText(ip);
        portEt.setText(""+port);
        deviceNo.setText(deviceno);
        workNo.setText(workno);
        outCallTx.setText(outcallNum);

        AlertDialog alertDialog = new AlertDialog.Builder(this)
                .setView(view).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                }).setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ip = ipEt.getText().toString();
                        port = Integer.valueOf(portEt.getText().toString());
                        deviceno = deviceNo.getText().toString();
                        workno = workNo.getText().toString();
                        outcallNum = outCallTx.getText().toString();
                        if (gson == null) {
                            gson = new GsonBuilder().registerTypeAdapter(UIPMessage.class,new UIPMessageAdapter()).create();
                        }
                        configAPI = new Retrofit.Builder()
                                .addConverterFactory(GsonConverterFactory.create(gson))
                                .baseUrl(new HttpUrl.Builder().scheme("http").host(ip).port(port).build())
                                .build().create(ConfigAPI.class);
                        retrofit2.Call<UIPConfig> call = configAPI.getSIPServer(UIPRequest.getConfigRequest(workno,deviceno).toJson());
                        call.enqueue(new Callback<UIPConfig>() {
                            @Override
                            public void onResponse(retrofit2.Call<UIPConfig> call, Response<UIPConfig> response) {
                                config = response.body();
                                modifyAccount(
                                        "sip:"+deviceno,
                                        "sip:"+config.AsteriskIP+":"+config.AsteriskPort,
                                        "",
                                        deviceno,
                                        ""
                                );
                                if (socketClient != null) {
                                    socketClient.disconnect();
                                    socketClient = null;
                                }
                                socketClient = new SocketIOClient(
                                        config.WebHttpIP,config.token,config.WebHttpPort,socketCallback
                                );
                                socketClient.setHeartMessage(gson.toJson(UIPMessage.getHeartbeat()));
                                socketClient.connect();
                            }

                            @Override
                            public void onFailure(retrofit2.Call<UIPConfig> call, Throwable t) {
                                Log.e("Failed",call.request().toString(),t);
                                Toast.makeText(getApplicationContext(),"获取配置失败",Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                })
                .create();

        alertDialog.show();
    }

    private SocketClient.Callback socketCallback = new SocketClient.Callback() {
        @Override
        public void onSend(String ms) {
            final UIPMessage message = gson.fromJson(ms,UIPMessage.class);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    addMessage(message.id);
                }
            });
        }

        @Override
        public void onReceived(String incomingMessage) {
            final UIPMessage message = gson.fromJson(incomingMessage,UIPMessage.class);
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    addMessage(message.id);
                }
            });

        }

        @Override
        public void onConnected() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    addMessage("建立连接");
                }
            });


        }

        @Override
        public void onConnecting() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    addMessage("建立连接中");
                }
            });

        }

        @Override
        public void onDisconnected() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    addMessage("断开连接");
                }
            });
        }

        @Override
        public void onError(Throwable e) {
            e.printStackTrace();
        }
    };

    // function to append a string to a TextView as a new line
// and scroll to the bottom if needed
    private void addMessage(String msg) {
        // append the new string
        socketStatus.append(msg + "\n");
        // find the amount we need to scroll.  This works by
        // asking the TextView's internal layout for the position
        // of the final line and then subtracting the TextView's height
        final int scrollAmount = socketStatus.getLayout().getLineTop(socketStatus.getLineCount()) - socketStatus.getHeight();
        // if there is no need to scroll, scrollAmount will be <=0
        if (scrollAmount > 0)
            socketStatus.scrollTo(0, scrollAmount);
        else
            socketStatus.scrollTo(0, 0);
    }

}
